package cn.ecnu.common.utils;

import cn.hutool.core.io.FileTypeUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;

public class ImageUtil {

    /**
     * [图片转换格式，压缩公共方法] 统一压缩成jpg
     * @param multipartFile 原图
     * @return 返回一个压缩后的jpg文件
     * @throws IOException io异常
     */
    public static MultipartFile getCompressFile(String rootPath, MultipartFile multipartFile) throws IOException {
        List fileTypeList = new ArrayList(){{add("jpg");}};  //设成list为了方便可扩展其他的图片格式，目前只支持jpg
        String filePath = rootPath + "temp/" + UUID.randomUUID() + ".jpg";
//        LOGGER.info("缓存文件的绝对路径：" + filePath);
        //图片压缩
        return compressFile(multipartFile, filePath, fileTypeList);
    }

    private static MultipartFile compressFile(MultipartFile file, String absolutePath, List<String> fileTypeList) throws IOException {
        //记录原MultipartFile，如果压缩异常就用原来的MultipartFile
        MultipartFile oldMultipartFile = file;
        FileInputStream fileInputStream = null;
        try {
            String fileName = file.getName();
            String originalFilename = file.getOriginalFilename();
            String contentType = file.getContentType();
            //获取要上传的文件后缀
            String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            File tempFile = new File(absolutePath);
            file.transferTo(tempFile);
            if (fileTypeList.contains(fileSuffix)) {
                //如果文件类型符合，则只压缩就好了
                Thumbnails.of(file.getInputStream())
                        .scale(1f)
                        .outputQuality(0.2f)
                        .toFile(tempFile);
            } else {
                //如果文件类型不在指定的集合内。则要转格式，并压缩
                Thumbnails.of(file.getInputStream())
                        .scale(1f)
                        .outputFormat(fileTypeList.get(0))
                        .outputQuality(0.2f)
                        .toFile(tempFile);
                originalFilename = originalFilename.replace("." + fileSuffix, "." + fileTypeList.get(0));
            }
            fileInputStream = new FileInputStream(tempFile);
            file = new MockMultipartFile(fileName, originalFilename, contentType, fileInputStream);
            boolean success = tempFile.delete();
//            logger.info("删除临时file success：{}", success);
        } catch (IOException e) {
//            logger.error("压缩图片失败,把MultipartFile赋值为原来的值oldFile,exception：{}", e);
            file = oldMultipartFile;
        } finally {
            if(fileInputStream!=null)
                fileInputStream.close();
        }
        return file;
    }





    private static final String imageType = "image";

    public static boolean checkFileType(MultipartFile multipartFile) throws Exception {
        // 打印文件字节头
        System.out.println(bytesToHexString(multipartFile.getBytes()).substring(0, 20));
        // 限制的文件类型集合
        Set<String> fileType = new HashSet<String>(){{add("jpg");add("png");add("heic");}};
//        Set<String> fileType = Set.of("jpg", "png", "heic");
        // 将自定义的文件类型字节头添加到工具类的Map中
        FileTypeUtil.putFileType("000000286674", "heic");
        // 检查文件类型
        String type = FileTypeUtil.getType(multipartFile.getInputStream());
        // 判断是否在限制的文件类型集合中，如果为null，直接返回false
        if (!Optional.ofNullable(type).map(fileType::contains).orElse(false)) {
            return false;
        }
        // 判断content type是不是image
        if (!multipartFile.getContentType().contains(imageType)) {
            return false;
        }
        // 判断图片尺寸
        if (!isImage(multipartFile.getInputStream())) {
            return false;
        }
        return true;
    }

    /**
     * 检查文件字节头
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * 通过图片尺寸，判断宽和高是否大于0，校验是否为图片
     */
    private static boolean isImage(InputStream in) throws IOException {
        try {
            Image img = ImageIO.read(in);
            return !(img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0);
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }


}
